module fasthttpd.HttpResponse;

import fasthttpd.HttpStatusCode;
import fasthttpd.HttpContext;

import std.format;
import std.array;

class HttpResponse
{
    alias string[string]   headerList;

    ushort       _status = HttpStatusCode.OK;
    headerList   _headers;
    string       _body;
    string       _buffer;
	HttpContext  _httpContext;

public:
    /*
     * Construct an empty response.
     */
    this(HttpContext ctx)
    {
		_httpContext = ctx;
    }

    /*
     * Sets a header field.
     *
     * Setting the same header twice will overwrite the previous, and header keys are case
     * insensitive. When sent to the client the header key will be as written here.
     *
     * @param header the header key
     * @param value the header value
     */
    HttpResponse set_header(string header, string value)
    {
		_headers[header] = value;
		
		return this;
    }

    /*
     * Set the HTTP status of the response.
     *
     * @param status_code the status code
     */
    HttpResponse set_status(HttpStatusCode status_code)
    {
        _status = status_code;

		return this;
    }

    /*
     * Set the entire body of the response.
     *
     * Sets the body of the response, overwriting any previous data stored in the body.
     *
     * @param body the response body
     */
    HttpResponse set_body(string body)
    {
		_body = body;

		return this;
    }

    /*
     * Set the entire response.
     *
     * Sets the entire response, discarding any previous data stored in both the headers and the body.
     *
     * @param res the response buffer
     */
    // HttpResponse set_response(string res)
    // {
    //     // TODO
    // }

    /*
     * Get the status of the response.
     *
     * @return the status of the response
     */
    ushort status_code()
    {
		return _status;
    }

    /*
     * Get the byte count of the response body.
     *
     * @return the size of the response body
     */
    size_t body_size()
    {
		return _body.length;
    }

    //  -----  serializer  -----

    /*
     * Generate an HTTP response from this object.
     *
     * Uses the configured parameters to generate a full HTTP response and returns it as a
     * string.
     *
     * @return the HTTP response
     */
    ubyte[] to_buffer()
	{
        auto app = appender!string;
        app ~= format!"HTTP/1.1 %d %s\r\n"(_status, getHttpStatusMessage(_status));
        foreach (name, value; _headers) {
            app ~= format!"%s: %s\r\n"(name, value);
        }
        app ~= "\r\n";

		app ~= _body.dup;
		
		return cast(ubyte[]) app[];
    }
}
